package cn.devcat.sso.service.impl;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;

import cn.devcat.sso.config.exception.DevcatApiPatternException;
import cn.devcat.sso.entity.DevcatApiPattern;
import cn.devcat.sso.entity.DevcatRole;
import cn.devcat.sso.entity.PageData;
import cn.devcat.sso.entity.SearchCommonParam;
import cn.devcat.sso.mapper.DevcatApiPatternMapper;
import cn.devcat.sso.service.IDevcatApiPatternService;
import cn.devcat.sso.service.IDevcatRoleService;
import cn.devcat.sso.util.PageHelperUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class DevcatApiPatternServiceImpl extends ServiceImpl<DevcatApiPatternMapper, DevcatApiPattern> implements IDevcatApiPatternService {
	
	@Resource
	DevcatApiPatternMapper mapper;
	
	@Autowired
	IDevcatRoleService roleService;
	
	@Autowired
	ThreadPoolTaskExecutor threadTaskExecutor;

	/**
	 * 添加api匹配
	 * @throws DevcatApiPatternException 
	 */
	@CacheEvict(cacheNames={"apiPatternList","roleListByApiPatternId"}, allEntries = true)
	@Override
	public void addApiPattern(DevcatApiPattern apiPattern) throws DevcatApiPatternException {
		if(StringUtils.isEmpty(apiPattern.getApiPattern())) {
			throw new DevcatApiPatternException("API匹配字符串不能为空");
		}
		apiPattern.setCreateTime(LocalDateTime.now());
		checkIsSameApi(apiPattern);
		save(apiPattern);
		//如果角色列表参数不为空则调用绑定方法进行绑定
		if(apiPattern.getRoleList()!=null && !apiPattern.getRoleList().isEmpty()) {
			for(DevcatRole role : apiPattern.getRoleList()) {
				bindApiParrentAndRole(apiPattern.getId(), role.getId());
			}
			log.info("bind role for api pattern : {}", apiPattern.getApiPattern());
		}
		log.info("save api pattern successful");
	}

	/**
	 * 绑定角色到API匹配模式
	 */
	@Override
	public void bindApiParrentAndRole(String apiParrentId, String roleId) {
		if(StringUtils.isEmpty(apiParrentId) || StringUtils.isEmpty(roleId)) {
			throw new DevcatApiPatternException("API模式匹配ID与角色ID必须不为空");
		}
		mapper.bindApiPatternAndRole(apiParrentId, roleId);
		log.info("bind api_pattern_id and role id successful");
	}

	/**
	 * 删除API匹配模式
	 */
	@CacheEvict(cacheNames={"apiPatternList","roleListByApiPatternId"}, allEntries = true)
	@Transactional
	@Override
	public void removeApiPattern(List<String> ids) {
		//首先删除绑定表中的内容
		mapper.unBindApiPatternAndRole(ids);
		//最后删除本表记录
		removeByIds(ids);
		log.info("remove api pattern successful : {}",ids);
	}

	/**
	 * 更新API匹配模式
	 * @throws DevcatApiPatternException 
	 */
	@CacheEvict(cacheNames={"apiPatternList","roleListByApiPatternId"}, allEntries = true)
	@Transactional
	@Override
	public void updateApiPattern(DevcatApiPattern apiPattern) {
		if(StringUtils.isEmpty(apiPattern.getId())||StringUtils.isEmpty(apiPattern.getApiPattern())) {
			throw new DevcatApiPatternException("更新的ID或模式字符串为空，请检查请求参数");
		}
		checkIsSameApi(apiPattern);
		updateById(apiPattern);
		//如果角色列表不为空则更新，更新前先解绑，然后重新绑定
		mapper.unBindApiPatternAndRole(Arrays.asList(apiPattern.getId()));
		if(apiPattern.getRoleList()!=null&&!apiPattern.getRoleList().isEmpty()) {
			for(DevcatRole role : apiPattern.getRoleList()) {
				bindApiParrentAndRole(apiPattern.getId(), role.getId());
			}
		}
		
	}

	/**
	 * 查询列表
	 */
	@Override
	public PageData<DevcatApiPattern> listApiPattern(SearchCommonParam param) {
		QueryWrapper<DevcatApiPattern> queryWrapper = new QueryWrapper<>();
		if(StringUtils.isNotEmpty(param.getKeyword())) {
			queryWrapper.like("api_pattern", param.getKeyword()).or().like("api_describe", param.getKeyword());
		}
		queryWrapper.orderByDesc("create_time");
		PageHelperUtil.handle(param);
		List<DevcatApiPattern> list = list(queryWrapper);
		addRoleListForApiPattern(list);
		return PageHelperUtil.makePageData(new PageInfo<>(list));
	}
	
	
	/**
	 * 查询所有集合
	 */
	@Cacheable(cacheNames="apiPatternList")
	@Override
	public List<DevcatApiPattern> getAllApiParrentList() {
		return list();
	}

	private void checkIsSameApi(DevcatApiPattern apiPattern) {
		long count = count(new QueryWrapper<DevcatApiPattern>().ne("id", apiPattern.getId()).eq("api_pattern", apiPattern.getApiPattern()));
		if(count > 0) {
			throw new DevcatApiPatternException(apiPattern.getApiPattern()+"已经存在，更新失败");
		}
	}
	
	private void addRoleListForApiPattern(List<DevcatApiPattern> list) {
		//采用多线程并行执行
		@SuppressWarnings("rawtypes")
		CompletableFuture[] future= list.stream().map(item->CompletableFuture
				.runAsync(()->{
					item.setRoleList(roleService.getRoleListByApiPatternId(item.getId()));
				},threadTaskExecutor)).toArray(CompletableFuture[]::new);
		//汇总结果
		CompletableFuture.allOf(future).join();
//		list.forEach(item->item.setRoleList(roleService.getRoleListByApiPatternId(item.getId())));
	}

}
